using Lzfy_Refund_Service.Models;
using Lzfy_Refund_Service.Repositories;
using Microsoft.Extensions.Logging;

namespace Lzfy_Refund_Service.Services
{
    /// <summary>
    /// 退费流程服务实现
    /// </summary>
    public class RefundProcessService : IRefundProcessService
    {
        private readonly IPatientRefundPasswordService _passwordService;
        private readonly IVerifyInfoService _verifyInfoService;
        private readonly IPatientRefundPasswordRepository _passwordRepository;
        private readonly IPasswordUpdateTaskService _taskService;
        private readonly ILogger<RefundProcessService> _logger;

        public RefundProcessService(
            IPatientRefundPasswordService passwordService,
            IVerifyInfoService verifyInfoService,
            IPatientRefundPasswordRepository passwordRepository,
            IPasswordUpdateTaskService taskService,
            ILogger<RefundProcessService> logger)
        {
            _passwordService = passwordService;
            _verifyInfoService = verifyInfoService;
            _passwordRepository = passwordRepository;
            _taskService = taskService;
            _logger = logger;
        }

        /// <summary>
        /// 等待HIS退费处理
        /// 实现补偿事务模式，确保两个数据库操作的一致性
        /// </summary>
        /// <param name="request">等待HIS退费请求</param>
        /// <returns>处理结果</returns>
        public async Task<WaitForHisRefundResponse> WaitForHisRefundAsync(WaitForHisRefundRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            _logger.LogInformation("开始处理等待HIS退费请求，患者ID: {PatientId}", request.PatientId);

            // 验证关键参数
            if (string.IsNullOrWhiteSpace(request.OrgPassword))
            {
                _logger.LogWarning("原密码为空，患者ID: {PatientId}", request.PatientId);
                return new WaitForHisRefundResponse
                {
                    Success = false,
                    Message = "原密码不能为空",
                    PatientId = request.PatientId
                };
            }

            if (string.IsNullOrWhiteSpace(request.VerifyCode))
            {
                _logger.LogWarning("验证码为空，患者ID: {PatientId}", request.PatientId);
                return new WaitForHisRefundResponse
                {
                    Success = false,
                    Message = "验证码不能为空",
                    PatientId = request.PatientId
                };
            }

            DateTime? hisUpdateTime = null;
            int? verifyInfoId = null;
            bool needRollback = false;

            try
            {
                // 第一步：更新HIS数据库（包括插入密码日志）
                _logger.LogInformation("步骤1：更新HIS数据库，患者ID: {PatientId}", request.PatientId);
                
                var passwordUpdateRequest = new PatientRefundPasswordUpdateRequest
                {
                    PatientId = request.PatientId,
                    RefundPassword = request.RefundPassword,
                    Modifier = request.Modifier,
                    ModifierCardType = request.ModifierCardType,
                    ModifierCardCode = request.ModifierCardCode,
                    OrgPassword = request.OrgPassword,
                    ModifyTime = DateTime.Now
                };

                var passwordUpdateResponse = await _passwordService.UpdatePatientRefundPasswordAsync(passwordUpdateRequest);
                
                if (!passwordUpdateResponse.Success)
                {
                    _logger.LogWarning("HIS数据库更新失败，患者ID: {PatientId}，错误: {Message}", 
                        request.PatientId, passwordUpdateResponse.Message);
                    
                    return new WaitForHisRefundResponse
                    {
                        Success = false,
                        Message = $"HIS数据库更新失败: {passwordUpdateResponse.Message}",
                        PatientId = request.PatientId
                    };
                }

                hisUpdateTime = passwordUpdateResponse.ModifyTime;
                needRollback = true; // 标记需要回滚
                
                _logger.LogInformation("HIS数据库更新成功，患者ID: {PatientId}，更新时间: {UpdateTime}", 
                    request.PatientId, hisUpdateTime);

                // 第二步：创建验证码信息
                _logger.LogInformation("步骤2：创建验证码信息，患者ID: {PatientId}", request.PatientId);
                
                var verifyInfoRequest = new VerifyInfoCreateRequest
                {
                    PatientId = request.PatientId,
                    VerifyCode = request.VerifyCode,
                    QrCode = request.QrCode,
                    RefundBalance = request.RefundBalance,
                    UserId = request.UserId,
                    UserName = request.UserName,
                    PatName = request.PatName,
                    IdNumber = request.IdNumber
                };

                verifyInfoId = await _verifyInfoService.CreateAsync(verifyInfoRequest);
                
                _logger.LogInformation("验证码信息创建成功，患者ID: {PatientId}，验证码信息ID: {VerifyInfoId}", 
                    request.PatientId, verifyInfoId);

                // 第三步：创建定时任务
                _logger.LogInformation("步骤3：创建定时任务，患者ID: {PatientId}", request.PatientId);
                
                var taskRequest = new CreatePasswordUpdateTaskRequest
                {
                    PatientId = request.PatientId,
                    VerifyCode = request.VerifyCode,
                    VerifyInfoId = verifyInfoId.Value,
                    RefundPassword = request.RefundPassword,
                    Modifier = request.Modifier,
                    ModifierCardType = request.ModifierCardType,
                    ModifierCardCode = request.ModifierCardCode
                };

                var taskResponse = await _taskService.CreateTaskAsync(taskRequest);
                
                if (!taskResponse.Success)
                {
                    _logger.LogWarning("定时任务创建失败，患者ID: {PatientId}，错误: {Message}", 
                        request.PatientId, taskResponse.Message);
                    
                    // 定时任务创建失败，需要回滚验证码信息和HIS数据
                    // 这里可以考虑是否要回滚，或者记录错误但继续
                    _logger.LogWarning("定时任务创建失败，但HIS数据和验证码信息已创建，患者ID: {PatientId}", request.PatientId);
                }
                else
                {
                    _logger.LogInformation("定时任务创建成功，患者ID: {PatientId}，任务ID: {TaskId}，计划执行时间: {ScheduledTime}", 
                        request.PatientId, taskResponse.TaskId, taskResponse.ScheduledTime);
                }

                // 所有步骤完成，清除回滚标记
                needRollback = false;

                return new WaitForHisRefundResponse
                {
                    Success = true,
                    Message = "等待HIS退费处理成功",
                    PatientId = request.PatientId,
                    HisUpdateTime = hisUpdateTime,
                    VerifyInfoId = verifyInfoId,
                    Details = taskResponse?.Success == true 
                        ? $"HIS数据库更新时间: {hisUpdateTime}, 验证码信息ID: {verifyInfoId}, 定时任务ID: {taskResponse.TaskId}, 计划执行时间: {taskResponse.ScheduledTime}"
                        : $"HIS数据库更新时间: {hisUpdateTime}, 验证码信息ID: {verifyInfoId}, 定时任务创建失败: {taskResponse?.Message}"
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "等待HIS退费处理异常，患者ID: {PatientId}", request.PatientId);

                // 如果需要回滚且有更新时间，尝试回滚HIS操作
                if (needRollback && hisUpdateTime.HasValue)
                {
                    _logger.LogWarning("开始回滚HIS数据库操作，患者ID: {PatientId}，更新时间: {UpdateTime}", 
                        request.PatientId, hisUpdateTime.Value);
                    
                    try
                    {
                        var rollbackSuccess = await RollbackHisRefundLogAsync(request.PatientId, hisUpdateTime.Value);
                        if (rollbackSuccess)
                        {
                            _logger.LogInformation("HIS数据库回滚成功，患者ID: {PatientId}", request.PatientId);
                        }
                        else
                        {
                            _logger.LogError("HIS数据库回滚失败，患者ID: {PatientId}，需要人工处理", request.PatientId);
                        }
                    }
                    catch (Exception rollbackEx)
                    {
                        _logger.LogError(rollbackEx, "HIS数据库回滚异常，患者ID: {PatientId}，需要人工处理", request.PatientId);
                    }
                }

                return new WaitForHisRefundResponse
                {
                    Success = false,
                    Message = $"等待HIS退费处理失败: {ex.Message}",
                    PatientId = request.PatientId,
                    HisUpdateTime = hisUpdateTime,
                    VerifyInfoId = verifyInfoId,
                    Details = needRollback ? "已尝试回滚HIS数据库操作" : "无需回滚"
                };
            }
        }

        /// <summary>
        /// 回滚HIS退费密码日志
        /// 删除指定时间的密码修改日志记录
        /// </summary>
        /// <param name="patientId">患者ID</param>
        /// <param name="modifyTime">修改时间</param>
        /// <returns>是否回滚成功</returns>
        public async Task<bool> RollbackHisRefundLogAsync(string patientId, DateTime modifyTime)
        {
            try
            {
                _logger.LogInformation("开始回滚HIS退费密码日志，患者ID: {PatientId}，修改时间: {ModifyTime}", 
                    patientId, modifyTime);

                // 调用Repository的回滚方法
                var success = await _passwordRepository.DeleteRefundPasswordLogAsync(patientId, modifyTime);
                
                if (success)
                {
                    _logger.LogInformation("HIS退费密码日志回滚成功，患者ID: {PatientId}", patientId);
                }
                else
                {
                    _logger.LogWarning("HIS退费密码日志回滚失败，未找到匹配的记录，患者ID: {PatientId}", patientId);
                }

                return success;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "HIS退费密码日志回滚异常，患者ID: {PatientId}", patientId);
                return false;
            }
        }
    }
}